import 'dart:typed_data';

import 'package:fluwx/fluwx.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_log.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_string.dart';

/*
微信: 支付,分享  android iOS
https://pub-web.flutter-io.cn/packages/fluwx
https://github.com/OpenFlutter/fluwx/blob/master/README_CN.md
https://github.com/OpenFlutter/fluwx/blob/master/example/lib/pages/share_text_page.dart

dependencies:
  fluwx: ^4.5.5
import 'package:fluwx/fluwx.dart';


其他第三方wechat_kit:
https://pub-web.flutter-io.cn/packages/wechat_kit

 */
abstract class XWeixinUtils{

  static Fluwx? _fluwx;
  static String? _weixinAppID;

  //1.初始化(使用之前初始化)
  static void init(
      {
        required String weixinAppID, //"wxd930ea5d5a228f5f"
      }
      ){

    //注册
    _weixinAppID=weixinAppID;

    if(_fluwx!=null){
      _fluwx!.clearSubscribers();
      _fluwx=null;
    }

    _fluwx = Fluwx();
    _fluwx!.registerApi(
        appId: weixinAppID,
        universalLink: "https://help.wechat.com/app/"
    );

    /*
    微信响应回调
    实际上，像shareToWeChat or payWithWeChat这种的函数，底层上是调用了原生SDK的sendRequest方法，
    所以他们的返回结果意义不大，他们的返回结果仅仅是sendRequest的返回值。
    如果你的 errCode = -1, 那请阅读微信官方文档，因为-1的原因数不胜数.

    从微信标签打开应用:
    微信开放标签 <wx-open-launch-app> 跳转App https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html#%E8%B7%B3%E8%BD%ACAPP%EF%BC%9Awx-open-launch-app
    App获取开放标签 <wx-open-launch-app> 中的 extinfo 数据 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/APP_GET_EXTINF.html
    安卓端 微信唤起App 的事件类型为 WeChatShowMessageFromWXRequest
    IOS端 微信唤起App 的事件类型为 WeChatLaunchFromWXRequest
    如你想主动获取从网页传进来的值 ，请主动调用fluwx.getExtMsg()。更多信息请参考example项目.
    /// Try to reload data from cold boot. For example, the app is launched by mini program and
    /// we can get ext message by calling this.
    _fluwx?.attemptToResumeMsgFromWx();
     */
    var cancelable = _fluwx!.addSubscriber((WeChatResponse response){
      XLogUtils.printLog('---WeChatResponse=${response.toString()}');
      if (response is WeChatAuthResponse) {
        //通过微信登录(认证)响应
        XLogUtils.printLog('---WeChatAuthResponse=${response.toString()}');
      }else if (response is WeChatShowMessageFromWXRequest //android端微信唤起App响应
          ||response is WeChatLaunchFromWXRequest //iOS端微信唤起App响应
      ) {
        //response.extMsg
        XLogUtils.printLog('---launch-app-from-h5=${response.toString()}');
      }else if (response is WeChatPaymentResponse) {
        //微信支付响应
        XLogUtils.printLog('---微信支付响应=${response.isSuccessful}');
      }if (response is WeChatLaunchMiniProgramResponse) {
        XLogUtils.printLog('---app打开小程序响应回调=${response.isSuccessful}');
      }

    }); // 订阅消息

    // 取消订阅消息:
    // cancelable.cancel();

  }

  /*
  2.1微信支付
  https://github.com/OpenFlutter/fluwx/blob/master/doc/PAYMENT_CN.md
  https://github.com/OpenFlutter/fluwx/blob/master/example/lib/pages/pay_page.dart
   */
  static void pay(
      {
        required String partnerId,
        required String prepayId,
        required String packageValue,
        required String nonceStr,
        required int timestamp,
        required String sign,
      }
      )async {

    bool? isWeChatInstalled= await _fluwx?.isWeChatInstalled;
    XLogUtils.printLog('---weixin pay isWeChatInstalled=$isWeChatInstalled');
    if(isWeChatInstalled==true){
      _fluwx?.pay(
          which: Payment(
            appId: _weixinAppID??'',
            partnerId: partnerId,
            prepayId: prepayId,
            packageValue: packageValue,
            nonceStr: nonceStr,
            timestamp: timestamp,
            sign: sign,
          )
      );
    }

  }

  //2.2打开小程序
  static void openMiniProgram(
      {
        required String userName, // 填小程序原始id "gh_d43f693ca31f"
        String? path,
      }
      ){
    _fluwx?.open(
        target: MiniProgram(
          username: userName,
          path: path,
          miniProgramType: WXMiniProgramType.release, //正式版
        )
    );
  }


  /*
  app应用一次性订阅消息授权
  https://developers.weixin.qq.com/doc/oplatform/Mobile_App/One-time_subscription_info.html
   */
  static void openSubscribeMessage(
      {
        required String templateId,//订阅消息模板 ID，在微信开放平台提交应用审核通过后获得
        int? scene,//重定向后会带上 scene 参数，开发者可以填 0-10000 的整型值，用来标识订阅场值
        String? reserved,//用于保持请求和回调的状态，授权请后原样带回给第三方。该参数可用于防止 csrf 攻击（跨站请求伪造攻击），建议第三方带上该参数，可设置为简单的随机数加 session 进行校验，开发者可以填写 a-zA-Z0-9 的参数值，最多 128 字节，要求做 urlencode
      }
      ){
    _fluwx?.open(
        target: SubscribeMessage(
          appId: _weixinAppID??'',
          scene: scene ?? 1,
          templateId: templateId,
          reserved: reserved,
        )
    );


  }



  /*
  移动应用微信登录是基于OAuth2.0 协议标准构建的微信 OAuth2.0 授权登录系统。
  https://github.com/OpenFlutter/fluwx/blob/master/doc/AUTH_CN.md
  https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.html
  为什么不支持获取用户信息？ 我认为获取用户信息应该后端来做，即使没有后端，你也可以在dart层自己实现.
   */
  static void loginAuth(
      {
        String? state,//用于保持请求和回调的状态，授权请求后原样带回给第三方。该参数可用于防止 csrf 攻击（跨站请求伪造攻击），建议第三方带上该参数，可设置为简单的随机数加 session 进行校验。在state传递的过程中会将该参数作为url的一部分进行处理，因此建议对该参数进行url encode操作，防止其中含有影响url解析的特殊字符（如'#'、'&'等）导致该参数无法正确回传。
      }
      ){
    _fluwx?.authBy(
        which: NormalAuth(
          scope: 'snsapi_userinfo',//应用授权作用域，获取用户个人信息则填写 snsapi_userinfo （只能填 snsapi_userinfo）
          state: state??'xsdk_wechat',
        )
    );

  }

  /*
  通过扫描微信二维码,让另一台设备登录登录
  https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Login_via_Scan.html
  签名生成
签名生成规则如下：
参与签名的字段包括第三方 appid，noncestr（随机字符串）, 有效的 sdk_ticket, timestamp（时间戳） 。
对所有待签名参数按照字段名（即key）的 ASCII 码从小到大排序（字典序）后，使用 URL 键值对的格式（即 key1=value1&key2=value2…）拼接成字符串 string1。 这里需要注意的是所有参数名均为小写字符。 对 string1 作 sha1 加密，字段名和字段值都采用原始值，不进行 URL 转义。即 signature=sha1(string1)。
示例：
appid=wxappid
sdk_ticket=-p3A5zVP95IuafPhzA6lRR95_F9nZEBfJ_n4E9t8ZFWKJTDPOwccVQhHCwDBmvLkayF_jh-m9HOExhumOziDWA
noncestr=noncestr
timestamp=1417508194
1.对所有待签名参数按照字段名（即key）的 ASCII 码从小到大排序（字典序）
appid、noncestr、sdk_ticket、timestamp
2.使用 URL 键值对的格式（即 key1=value1&key2=value2…）拼接成字符串 string1：
appid=wxappid&noncestr=noncestr&sdk_ticket=-p3A5zVP95IuafPhzA6lRR95_F9nZEBfJ_n4E9t8ZFWKJTDPOwccVQhHCwDBmvLkayF_jh-m9HOExhumOziDWA&timestamp=1417508194
3.对 string1 进行 sha1 签名，得到 signature： 429eaaa13fd71efbc3fd344d0a9a9126835e7303
   */
  static void loginAuthByScanQr(
      {
        required String scope,//应用授权作用域，拥有多个作用域用逗号（,）分隔，APP 所拥有的 scope
        required String nonceStr,//一个随机的尽量不重复的字符串，用来使得每次的 signature 不同
        required String timestamp,//时间戳
        required String signature,//签名
      }
      ){

    _fluwx?.authBy(
        which: QRCode(
            appId: _weixinAppID??'',
            scope: scope,
            nonceStr: nonceStr,
            timestamp: timestamp,
            signature: signature
        )
    );


  }


  /*
  APP纯签约
  https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_2.shtml
  _fluwx?.autoDeduct(
        data: AutoDeduct.detail(
          appId: appId.text,
          mchId: mchId.text,
          planId: planId.text,
          contractCode: contractCode.text,
          requestSerial: requestSerial.text,
          contractDisplayAccount: contractDisplayAccount.text,
          notifyUrl: notifyUrl.text,
          version: version.text,
          sign: sign.text,
          timestamp: timestamp.text,
          returnApp: '3',
        ));
   */



  //分享////////////////////////////
  /*
  支持的分享各类:
  WeChatShareTextModel
  WeChatShareMiniProgramModel
  WeChatShareImageModel
  WeChatShareMusicModel
  WeChatShareVideoModel
  WeChatShareWebPageModel
  WeChatShareFileModel

  图片有四种内置 WeChatImage:
  WeChatImage.network(String source, {String suffix});
  WeChatImage.file(File source, {String suffix = ".jpeg"});
  WeChatImage.asset(String source, {String suffix});
  WeChatImage.binary(Uint8List source, {String suffix = ".jpeg"});
  其中， suffix 优先级最高, 如果suffix是空白的，fluwx 将会尝试从文件路径中读取后缀.
   */


  //分享小程序
  static void shareMiniProgram(
      {
        required String userName, // 填小程序原始id "gh_d43f693ca31f"
        required String? imageUrl,//设置缩略图,小程序消息封面图片,小于128k, 图片类型'.jpeg'  注意:不能为null,否则无法发起分享
        required String? imageAssetName,//设置缩略图,小程序消息封面图片,小于128k, 图片类型'.jpeg'  注意:不能为null,否则无法发起分享
        String path="/", //拉起小程序页面的可带参路径，不填默认拉起小程序首页，对于小游戏，可以只传入 query 部分，来实现传参效果，如：传入 "?foo=bar"。
        String? webPageUrl,// 兼容低版本的网页链接
        String? title,
        String? description,
      }
      ){

    //缩略图必须存在
    WeChatImage thumbnail;
    if(!XStringUtils.isEmpty(imageUrl)){
      thumbnail=WeChatImage.network(imageUrl!);
    }else if(!XStringUtils.isEmpty(imageAssetName)){
      thumbnail=WeChatImage.asset('assets/images/$imageAssetName');
    }else{
      thumbnail=WeChatImage.binary(Uint8List.fromList([]));
    }

    _fluwx?.share(
        WeChatShareMiniProgramModel(
          miniProgramType: WXMiniProgramType.release, //正式版
          webPageUrl: webPageUrl??'https://www.qq.com',
          path: path,
          userName: userName,
          title:title,
          description: description,
          thumbnail: thumbnail,
        )
    );
  }

  //分享文字
  static void shareText(
      {
        required String text,
        String? title,
        String? description,
        int scene=0,//0 朋友, 1 朋友圈, favorite 收藏
      }
      ){
    _fluwx?.share(
        WeChatShareTextModel(
            text,
            scene: scene==0?WeChatScene.session:WeChatScene.timeline,
          title: title,
          description: description,
        )
    );
  }

  //分享文字
  static void shareWeb(
      {
        required String webPage,
        String? title,
        String? description,
        String? imageUrl,
        String? imageAssetName,
        int scene=0,//0 朋友, 1 朋友圈, favorite 收藏
      }
      ){

    WeChatImage? thumbnail;
    if(!XStringUtils.isEmpty(imageUrl)){
      thumbnail=WeChatImage.network(imageUrl!);
    }else if(!XStringUtils.isEmpty(imageAssetName)){
      thumbnail=WeChatImage.asset('assets/images/$imageAssetName');
    }

    _fluwx?.share(
        WeChatShareWebPageModel(
          webPage,
          scene: scene==0?WeChatScene.session:WeChatScene.timeline,
          title: title,
          description: description,
          thumbnail: thumbnail,
        )
    );
  }

  /*
  分享图片
  在分享图片的功能，图片不能超过10M.如果图片被用作thumbnail 或 hdImagePath，Fluwx 会对 WeChatImage 进行压缩,
  否则不会压缩. 但是，最好还是自己压缩，因为不保证fluwx压缩效果。
   */
  static void shareImage(
      {
        required String? imageUrl,
        required String? imageAssetName,
        int scene=0,//0 朋友, 1 朋友圈, favorite 收藏
      }
      ){

    WeChatImage? image;
    if(!XStringUtils.isEmpty(imageUrl)){
      image=WeChatImage.network(imageUrl!);
    }else if(!XStringUtils.isEmpty(imageAssetName)){
      image=WeChatImage.asset('assets/images/$imageAssetName');
    }else{
      image=WeChatImage.binary(Uint8List.fromList([]));
    }

    _fluwx?.share(
        WeChatShareImageModel(
          image,
          scene: scene==0?WeChatScene.session:WeChatScene.timeline,
        )
    );
  }


}

